﻿using CommonModel.DB;
using CommonModel.Field;
using CommonModel.Model;
using Microsoft.EntityFrameworkCore;
using NewLife.Log;
using PtlSave.Util;
using PtlSvr.CfgLoader.Schema;
using System;
using System.Collections.Generic;
using System.Data.Common;
using System.IO;

namespace PtlSvr.CfgLoader
{
    class SchemaServer
    {
        //配置字典
        public static Dictionary<string, SchemaDocument> SCHAMA_DICT = new Dictionary<string, SchemaDocument>();
        public static Dictionary<string, DllModel> dllModels = new Dictionary<string, DllModel>();

        //读取xml配置
        public static Dictionary<string, SchemaDocument> initSchemaMap(string path)
        {
            SCHAMA_DICT = new Dictionary<string, SchemaDocument>();
            string[] schemaFiles = Directory.GetFiles(path, "*.xml");
            if (null == schemaFiles || schemaFiles.Length == 0)
            {
                XTrace.WriteLine("文件夹[" + path + "]下没有xml文件！");
                return SCHAMA_DICT;
            }

            SchemaParseByConfig schemaParser = new SchemaParseByConfig();
            foreach (string file in schemaFiles)
            {
                SchemaDocument schDoc = schemaParser.parse(file);
                if (null != schDoc)
                {
                    //如果xmlType不为空，做处理
                    string schemaxmlType = schDoc.getXmlType();
                    if (schemaxmlType != "")
                    {
                        string[] xmlTypeArray = schemaxmlType.Split(",");
                        for (int i = 0; i < xmlTypeArray.Length; i++)
                        {
                            SCHAMA_DICT.Add(xmlTypeArray[i].Trim(), schDoc);
                        }
                    }
                    else
                    {
                        string schemaName = schDoc.getName();
                        SCHAMA_DICT.Add(schemaName, schDoc);
                    }
                }
            }
            return SCHAMA_DICT;
        }

        //读取xml配置
        //从数据库读取
        public static Dictionary<string, SchemaDocument> initSchemaMapFromDb(MySQLContext mySQLContext)
        {
            Dictionary<string, SchemaDocument> tmpDict = new Dictionary<string, SchemaDocument>();
            SCHAMA_DICT = new Dictionary<string, SchemaDocument>();

            //从主表获取
            DbCommand dbCommand = mySQLContext.Database.GetDbConnection().CreateCommand();
            dbCommand.CommandText = "SELECT id, file_name, schema_name, msg_type, xml_type FROM file_param_main where use_flag = 1 ORDER BY id";
            DbDataReader dataReader = dbCommand.ExecuteReader();
            while (dataReader.Read())
            {
                SchemaDocument schDoc = new SchemaDocument();
                schDoc.setName(dataReader.GetString(2));
                schDoc.setFile_name(dataReader.GetString(1));
                schDoc.setMsgType(dataReader.GetString(3));
                schDoc.setXmlType(dataReader.GetString(4));
                schDoc.setId(dataReader.GetValue(0).ToString());

                if (!tmpDict.ContainsKey(schDoc.getFile_name()))
                { 
                    tmpDict.Add(schDoc.getFile_name(), schDoc);
                }
            }

            string tableName = "file_param_detail";
            //根据层级初始化数据 
            int layerNum = 4;
            dataReader.Close();
            dbCommand.CommandText = "SELECT MAX(layer) layer FROM " + tableName;
            dataReader = dbCommand.ExecuteReader();
            if (dataReader.Read())
            {
                layerNum = int.Parse(dataReader.GetValue(0).ToString());
            }

            //循环获取配置元素数据
            foreach (string key in tmpDict.Keys)
            {
                SchemaDocument schDoc = tmpDict[key];
                Dictionary<int, Object> layerPre = new Dictionary<int, object>();
                for (int i = 0; i <= layerNum; i++)
                {
                    layerPre.Add(i, new Dictionary<int, Object>());
                }

                /*****************从明细表获取************************/
                dataReader.Close();
                dbCommand.CommandText = "SELECT id,main_id,file_name,parent_id,child_num,idx,parent_idx,name,type,size,device_type,loop_val,code,isalarm,alarmvalue,alarmname,issave,get_time, memo,layer" +
                    " FROM " + tableName + " a WHERE a.main_id = " + schDoc.getId() + " ORDER BY main_id, sort";
                dataReader = dbCommand.ExecuteReader();

                //动态字段
                Dictionary<string, string> dynamic = new Dictionary<string, string>();
                Dictionary<int, Object> schema = new Dictionary<int, Object>();
                while (dataReader.Read())
                {
                    //层级
                    int layer = int.Parse(dataReader.GetValue(19).ToString());
                    int childNum = int.Parse(dataReader.GetValue(4).ToString());
                    if (!"".Equals(dataReader.GetString(11)) && !CommonUtil.IsInt(dataReader.GetString(11)) && !dynamic.ContainsKey(dataReader.GetString(11)))
                    {
                        dynamic.Add(dataReader.GetString(11), dataReader.GetString(11));
                    }

                    if (layer == 0)
                    {
                        GetElement(dataReader, schema, childNum > 0 ? new SchemaDictionary() : new FieldSchema());
                        layerPre[layer] = schema[schema.Count - 1];
                    }
                    else
                    {
                        if ((((SchemaDictionary)layerPre[layer - 1])).getFieldDictionary() == null)
                        { 
                            ((SchemaDictionary)layerPre[layer - 1]).setFieldDictionary(new Dictionary<int, object>());
                        }
                        GetElement(dataReader, (((SchemaDictionary)layerPre[layer - 1])).getFieldDictionary(), childNum > 0 ? new SchemaDictionary() : new FieldSchema());
                        layerPre[layer] = (((SchemaDictionary)layerPre[layer - 1])).getFieldDictionary()[(((SchemaDictionary)layerPre[layer - 1])).getFieldDictionary().Count - 1];
                    }
                }
                dataReader.Close();
                schDoc.setDynamicParaDictionary(dynamic);
                schDoc.setFieldDictionary(schema);//将已读取XML文件后的XML字段规则放进schemaDocument
                /*****************从明细表获取************************/

                string schemaxmlType = schDoc.getXmlType();
                if (schemaxmlType != "")
                {
                    string[] xmlTypeArray = schemaxmlType.Split(",");
                    for (int i = 0; i < xmlTypeArray.Length; i++)
                    {
                        SCHAMA_DICT.Add(xmlTypeArray[i].Trim(), schDoc);
                    }
                }
                else
                {
                    SCHAMA_DICT.Add(schDoc.getName(), schDoc);
                }
            }
            XTrace.WriteLine(CommonUtil.GetFormatDatetime() + " SCHAMA_DICT.Count=" + SCHAMA_DICT.Count);
            return SCHAMA_DICT;
        }

        //子元素获取
        private static void GetElement(DbDataReader dataReader, Dictionary<int, Object> schema, Object field)
        {
            ((dynamic)field).setName(dataReader.GetString(7));
            ((dynamic)field).setIndex(int.Parse(dataReader.GetValue(5).ToString()));
            ((dynamic)field).setId(dataReader.GetValue(0).ToString());
            ((dynamic)field).setType(DataTypeUtils.getType(dataReader.GetString(8)));
            ((dynamic)field).setMemo(dataReader.GetString(18));
            ((dynamic)field).setSize(int.Parse(dataReader.GetValue(9).ToString()));
            ((dynamic)field).setDeviceType(dataReader.GetString(10));
            ((dynamic)field).setAlarm("1".Equals(dataReader.GetValue(13).ToString()));
            ((dynamic)field).setAlarmName(dataReader.GetString(14));
            ((dynamic)field).setAlarmValue(dataReader.GetString(15));
            ((dynamic)field).setLoop(dataReader.GetString(11));
            ((dynamic)field).setCode(dataReader.GetString(12));
            ((dynamic)field).setIsSave(dataReader.GetValue(16).ToString());
            ((dynamic)field).setLayer(int.Parse(dataReader.GetValue(19).ToString()));
            schema.Add(schema.Count, field);
        }
    }
}
